package com.market.plus.core.dao.jdbc.rowmapper;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;

public abstract class MultipleRowMapper<R, I>{
	/**
	 * Map a single root object R, where there may be multiple R rows for each child C.
	 */
	public R map(ResultSet rs) throws SQLException {
		R root = mapRoot(mapId(rs), rs);
		addChild(root, rs);
		while (rs.next()) {
			addChild(root, rs);			
		}
		return root;
	}

	/**
	 * Map root objects R into Collection<L> where there may be multiple R rows for each child C.
	 */
	public <L extends Collection<R>> L mapInto(L collection, ResultSet rs) throws SQLException {
		R root = null;
		I previousId = null;
		while (rs.next()) {
			I id = mapId(rs);
			if (!id.equals(previousId)) {
				root = mapRoot(id, rs);
				collection.add(root);
			}
			addChild(root, rs);
			previousId = id;
		}
		return collection;
	}

	// subclassing hooks
	
	/**
	 * Map the ID property for root entity R.
	 */
	protected abstract I mapId(ResultSet rs) throws SQLException;
	
	/**
	 * Map root object R including its direct properties and excluding child association properties.
	 */
	protected abstract R mapRoot(I id, ResultSet rs) throws SQLException;

	/**
	 * Map the next child object and add it to root object R. 
	 */
	protected abstract void addChild(R root, ResultSet rs) throws SQLException;
}
